﻿module Boxes

open StyledElements
open Dom
open TextRendering


type BoxSize = BoxSize of int*int with
    member this.width =
        let (BoxSize(width,height))=this
        width
    member this.height =
        let (BoxSize(width,height))=this
        height   

type LayoutedTextBox = LayoutedTextBox of IStyledText * System.Windows.Media.FormattedText * bool with
    member this.width =
        let (LayoutedTextBox(node,formattedText, breakAfter)) = this
        int(formattedText.Width)
    member this.widthIncludingTrailingWhitespace =
        let (LayoutedTextBox(node,formattedText, breakAfter)) = this
        int(formattedText.WidthIncludingTrailingWhitespace)
    member this.height =
        let (LayoutedTextBox(node,formattedText, breakAfter)) = this 
        int(formattedText.Height)       
    member this.element =
        let (LayoutedTextBox(node,formattedText, breakAfter)) = this
        node.element
    member this.formattedText =
        let (LayoutedTextBox(node,formattedText, breakAfter)) = this
        formattedText

(* A layout is a rectangle with position relative to parent, calculated size and child-layouts *)
type Layout =
    | ElementBoxLayout of BoxSize * IStyledElement * Children
    (* A box which does not correspond to a single element, for example a stack of lines *)
    | BoxLayout of BoxSize * Children
    (* The layout of the replaced canvas (not the containing box) *)
    | ReplacedContentLayout of BoxSize * IReplacedElement
    | TextBoxLayout of LayoutedTextBox     
    | NoLayout
    with      
    member this.size : BoxSize =
        match this with
        | ElementBoxLayout(bosSixe, elem, children) -> bosSixe
        | BoxLayout(bosSixe, children) -> bosSixe
        | ReplacedContentLayout(bosSixe, elem) -> bosSixe
        | TextBoxLayout(sized) -> BoxSize(sized.width, sized.height)
        | NoLayout -> BoxSize(0,0)  
    member this.children =
        match this with
        | ElementBoxLayout(bosSixe, elem, children) -> children
        | BoxLayout(bosSixe, children) -> children
        | ReplacedContentLayout(bosSixe, elem) -> []
        | TextBoxLayout(sized) -> []      
        | NoLayout -> []
    member this.element =
        (* used by pointer event targeting *)
        match this with
        | ElementBoxLayout(bosSixe, elem, children) -> Some(elem.element)
        | BoxLayout(bosSixe, children) -> None
        | ReplacedContentLayout(bosSixe, elem) -> Some(elem :?> Element)
        | TextBoxLayout(sized) -> Some(sized.element)
        | NoLayout -> None

and PlacedLayout = (int*int)*Layout

and Children = PlacedLayout list



